package com.zp.resource.common;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.activation.MimetypesFileTypeMap;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.springframework.stereotype.Component;

import com.sun.jersey.core.header.FormDataContentDisposition;
import com.sun.jersey.multipart.FormDataParam;
import com.sun.jersey.spi.resource.Singleton;
import com.zp.bean.common.ContentBaseVo;
import com.zp.bean.common.ContentVo;
import com.zp.bean.common.ResultCommonVo;
import com.zp.bean.common.ResultContentBaseVo;
import com.zp.bean.common.ResultContentVo;
import com.zp.domain.Content;
import com.zp.util.Constant;
import com.zp.util.FileUtil;
import com.zp.util.MyException;

/**
 * News services
 * 
 * @author chenlijun08@gmail.com
 * 
 * @version 1.0
 * 
 * @date 2014/2/26
 * 
 */
@Component
@Path("/rest/news")
@Singleton
public class ContentServices extends BaseServices {

	/**
	 * publish content along with image or media
	 * 
	 * @param title
	 *            the tile of content
	 * @param content
	 *            the content of content
	 * @param author
	 *            the author of content
	 * @param source
	 *            where the content come from
	 * @param typeCode
	 *            which type of content
	 * @param top
	 *            whether put in head
	 * @param titleImage
	 *            the input stream of title image if have
	 * @param mediaType
	 *            the type of media
	 * @param mediaFile
	 *            the input stream of media file
	 * @return Response,ResultCommonVo with JSON String
	 *         like:{"code":268,"message":"OK","totalCount":1}
	 */
	@POST
	@Path("/uploadNews")
	@Consumes(MediaType.MULTIPART_FORM_DATA)
	@Produces(MediaType.APPLICATION_JSON)
	public Response addNews(
			@FormDataParam("title") String title,
			@FormDataParam("summary") String summary,
			@FormDataParam("content") String content,
			@FormDataParam("author") String author,
			@FormDataParam("source") String source,
			@FormDataParam("typeCode") String typeCode,
			@FormDataParam("top") String top,
			@FormDataParam("titleImage") InputStream titleImage,
			@FormDataParam("titleImage") FormDataContentDisposition fileDisposition,
			@FormDataParam("mediaFile") InputStream mediaFile,
			@FormDataParam("mediaFile") FormDataContentDisposition MediafileDisposition,
			@Context ServletContext context) {
		ResultCommonVo result = new ResultCommonVo();
		result.setCode(Constant.SUCCESS_CODE);
		result.setMessage(Constant.OK);
		String imagePath = FileUtil.getInstance().saveFile(titleImage,
				fileDisposition, context);
		if (imagePath == null
				|| !imagePath.equals(Constant.MAX_IMAGE_SIZE_MESSAGE)) {

			Content news = new Content();
			news.setAuthor(author);
			news.setContent(content);
			news.setCreateTime(new Date());
			news.setTitleImage(imagePath);
			news.setTitleImageMin(imagePath);
			news.setMediaPath(FileUtil.getInstance().saveFile(mediaFile,
					MediafileDisposition, context));
			news.setOperationTime(new Date());
			news.setSource(source);
			news.setStatus("1");
			news.setTitle(title);
			news.setSummary(summary);
			news.setTop(top);
			news.setTypeCode(typeCode);
			try {
				this.jpaDao.save(news);
			} catch (MyException e) {
				result.setCode(Constant.FAILE_CODE);
				result.setMessage(e.getMessage());
				e.printStackTrace();
			}

		} else {

			result.setCode(Constant.FAILE_CODE);
			result.setMessage(imagePath);

		}
		return Response.ok(result).build();
	}

	/**
	 * get news by id path:/news/getNews Http:POST
	 * 
	 * @param newsId
	 *            primary key of Content
	 * 
	 * @return Response,ResultContentVo with JSON String
	 *         like:{"code":268,"message":
	 *         "OK","totalCount":0,"content":{"id":3,"title"
	 *         :"心理关爱测试01新闻","operationTime"
	 *         :1393603880000,"top":"1","summary":null
	 *         ,"titleImage":"upload/image/20143101120.jpg","content":
	 *         "心理关爱测试01新闻心理关爱测试01新闻心理关爱测试01新闻心理关爱测试01新闻心理关爱测试01新闻心理关爱测试01新闻心理关爱测试01新闻心理关爱测试01新闻心理关爱测试01新闻心理关爱测试01新闻心理关爱测试01新闻"
	 *         ,"author":"Alex","source":"http://localhost:8082/TestWeb/",
	 *         "contentType"
	 *         :{"id":"402881e744791cd2014479213e260005","name":"心理关爱"
	 *         ,"code":"cm01"
	 *         ,"parentCode":"cm"},"status":"1","createTime":1393603880000
	 *         ,"mediaPath":null,"mediaType":null},"list":null}
	 */
	@POST
	@Path("/getNews")
	@Produces(MediaType.APPLICATION_JSON)
	public Response getNewsById(@QueryParam("newsId") int newsId) {
		logger.info("getNewsById called newsId:" + newsId);
		ResultContentVo result = new ResultContentVo();
		try {
			Content news = (Content) jpaDao.findById(Content.class, newsId);
			result.setCode(Constant.SUCCESS_CODE);
			result.setMessage(Constant.OK);
			if (news != null) {
				ContentVo vo = new ContentVo();
				vo.setAuthor(news.getAuthor());
				vo.setContent(news.getContent());
				vo.setCreateTime(news.getCreateTime());
				vo.setId(news.getId());
				vo.setMediaPath(news.getMediaPath());
				vo.setContentType(this.getContentTypeByCode(news.getTypeCode()));
				vo.setMediaType(this.getContentTypeByCode(news.getMediaType()));
				vo.setOperationTime(news.getOperationTime());
				vo.setSource(news.getSource());
				vo.setStatus(news.getStatus());
				vo.setTitle(news.getTitle());
				if (news.getTitleImage() != null) {
					vo.setTitleImage(news.getTitleImage());
				}
				vo.setTop(news.getTop());
				result.setContent(vo);
			}

		} catch (MyException e) {
			result.setCode(Constant.FAILE_CODE);
			result.setMessage(e.getMessage());
			e.printStackTrace();
		}
		return Response.ok(result).build();
	}

	/**
	 * delete Content by id path:/news/deleteNews Http:DELETE
	 * 
	 * @param newsId
	 *            primary key of News
	 * 
	 * @return Response,ResultCommonVo with JSON String
	 *         like:{"code":268,"message":"OK","totalCount":1}
	 */
	@DELETE
	@Path("/deleteNews")
	@Produces(MediaType.APPLICATION_JSON)
	public Response deleteNews(@QueryParam("newsId") int newsId) {
		logger.info("deleteNews called newsId:" + newsId);
		ResultCommonVo result = new ResultCommonVo();
		try {
			this.jpaDao.deleteById(Content.class, newsId);
			result.setCode(Constant.SUCCESS_CODE);
			result.setMessage(Constant.OK);
		} catch (MyException e) {
			result.setCode(Constant.FAILE_CODE);
			result.setMessage(e.getMessage());
			e.printStackTrace();
		}
		return Response.ok(result).build();
	}

	/**
	 * search news with filter parameters path:/news/searchNews Http:POST
	 * 
	 * @param pageNo
	 * 
	 * @param pageSize
	 * 
	 * @param value
	 *            the type code of news or the title of news or the author of
	 *            news,if ignore the default value will be null
	 * 
	 * @param top
	 *            whether put in first head value,if ignore the default value
	 *            will be null
	 * 
	 * @return Response, ResultNewsBaseVo with JSON String
	 *         like:{"code":268,"message"
	 *         :"OK","totalCount":4,"list":[{"id":6,"title"
	 *         :"心理关爱新闻4","operationTime"
	 *         :1393604703000,"top":"1","summary":"心理关爱新闻4","titleImageMin":
	 *         "http://localhost:8082/ZP/upload/image/201431215026.jpg"
	 *         },{"id":5,
	 *         "title":"心理关爱新闻3","operationTime":1393604641000,"top":"1"
	 *         ,"summary":"心理关爱新闻3","titleImageMin":
	 *         "http://localhost:8082/ZP/upload/image/20143101120.jpg"
	 *         },{"id":4,"title"
	 *         :"心理关爱测试02新闻","operationTime":1393603896000,"top"
	 *         :"1","summary":"心理关爱新闻2","titleImageMin":
	 *         "http://localhost:8082/ZP/upload/image/20143101120.jpg"
	 *         },{"id":3,"title"
	 *         :"心理关爱测试01新闻","operationTime":1393603880000,"top"
	 *         :"1","summary":"心理关爱新闻1","titleImageMin":
	 *         "http://localhost:8082/ZP/upload/image/20143101120.jpg"}]}
	 */
	@POST
	@Path("/searchNews")
	@Produces(MediaType.APPLICATION_JSON)
	public Response searchNewsByType(@QueryParam("pageNo") int pageNo,
			@QueryParam("pageSize") int pageSize,
			@QueryParam("value") String value, @QueryParam("top") String top) {
		logger.info("searchNewsByType called json pageNo:" + pageNo
				+ " pageSize:" + pageSize + " value:" + value + " top is:"
				+ top);
		String jpql = "select id,title,summary,titleImageMin,operationTime,top from Content where (author=? or typeCode=?) and top=? order by operationTime desc";
		List<?> list = null;
		ResultContentBaseVo result = new ResultContentBaseVo();
		List<ContentBaseVo> lt = new ArrayList<ContentBaseVo>();
		result.setCode(Constant.SUCCESS_CODE);
		result.setMessage(Constant.OK);
		if (("".equals(value) || value == null)
				&& ("".equals(top) || top == null)) {
			jpql = "select id,title,summary,titleImageMin,operationTime,top from Content order by operationTime desc";
			try {
				list = this.jpaDao.getResultData(pageNo, pageSize, jpql, null);
				long totalCount = this.jpaDao.getCount(
						"select count(id) from Content", null);
				result.setTotalCount(totalCount);
			} catch (MyException e) {
				result.setCode(Constant.FAILE_CODE);
				result.setMessage(e.getMessage());
				e.printStackTrace();
			}
		} else if (("".equals(value) || value == null)
				&& ((top != null) || !("").equals(top))) {
			jpql = "select id,title,summary,titleImageMin,operationTime,top from Content where top=? order by operationTime desc";

			Object[] param = { top };
			try {
				list = this.jpaDao.getResultData(pageNo, pageSize, jpql, param);
				long totalCount = this.jpaDao.getCount(
						"select count(id) from Content where top=?", param);
				result.setTotalCount(totalCount);
			} catch (MyException e) {
				result.setCode(Constant.FAILE_CODE);
				result.setMessage(e.getMessage());
				e.printStackTrace();
			}

		} else if ((value != null && !("".equals(top)))
				&& ((top == null) || ("".equals(top)))) {
			jpql = "select id,title,summary,titleImageMin,operationTime,top from Content where author=? or typeCode=? order by operationTime desc";
			Object[] param = { value, value };
			try {
				list = this.jpaDao.getResultData(pageNo, pageSize, jpql, param);
				long totalCount = this.jpaDao
						.getCount(
								"select count(id)from Content where author=? or typeCode=?",
								param);
				result.setTotalCount(totalCount);
			} catch (MyException e) {
				result.setCode(Constant.FAILE_CODE);
				result.setMessage(e.getMessage());
				e.printStackTrace();
			}
		} else {
			Object[] param = { value, value, top };
			try {
				list = this.jpaDao.getResultData(pageNo, pageSize, jpql, param);
				long totalCount = this.jpaDao
						.getCount(
								"select count(id)from Content where (author=? or typeCode=?) and top=?",
								param);
				result.setTotalCount(totalCount);
			} catch (MyException e) {
				result.setCode(Constant.FAILE_CODE);
				result.setMessage(e.getMessage());
				e.printStackTrace();
			}
		}
		if (list != null && list.size() > Constant.ZERO) {
			for (Object o : list) {
				Object[] news = (Object[]) o;
				ContentBaseVo vo = new ContentBaseVo();
				vo.setId(Integer.valueOf(String.valueOf((news[Constant.ZERO]))));
				vo.setTitle(String.valueOf(news[Constant.ONE]));
				vo.setSummary(String.valueOf(news[Constant.TWO]));
				if (news[Constant.THREE] != null) {
					vo.setTitleImage(this.serverPath
							+ String.valueOf(news[Constant.THREE]));
				}
				vo.setOperationTime((Date) news[Constant.FOUR]);
				vo.setTop(String.valueOf(news[Constant.FIVE]));
				lt.add(vo);
			}
			result.setList(lt);

		}
		return Response.ok(result).build();
	}

	/**
	 * get top Content with type
	 * 
	 * @param number
	 *            how many rows you want to fetch path:/news/searchTopNews
	 *            Http:POST
	 * @param typeCode
	 *            which kinds of type of Content,if ignore the default value
	 *            will be null
	 * @return Response ResultBaseVo with JSON String like:
	 *         {"code":268,"message"
	 *         :"OK","totalCount":3,"list":[{"id":6,"title":
	 *         null,"operationTime":null,"top":null,"summary":null,"titleImage":
	 *         "http://localhost:8082/ZP/upload/image/201431215026.jpg"
	 *         },{"id":5,
	 *         "title":null,"operationTime":null,"top":null,"summary":null
	 *         ,"titleImage"
	 *         :"http://localhost:8082/ZP/upload/image/201431215026.jpg"
	 *         },{"id":4
	 *         ,"title":null,"operationTime":null,"top":null,"summary":null
	 *         ,"titleImage"
	 *         :"http://localhost:8082/ZP/upload/image/201431215026.jpg"}]}
	 */

	@POST
	@Path("/searchTopNews")
	@Produces(MediaType.APPLICATION_JSON)
	public Response searchTopNews(@QueryParam("number") int number,
			@QueryParam("typeCode") String typeCode) {
		logger.info("searchNewsByType called json number:" + number
				+ " typeCode:" + typeCode);
		String jpql = "select id,titleImage from Content where typeCode=? and top=? order by operationTime desc";
		List<?> list = null;
		ResultContentBaseVo result = new ResultContentBaseVo();
		List<ContentBaseVo> lt = new ArrayList<ContentBaseVo>();
		result.setCode(Constant.SUCCESS_CODE);
		result.setMessage(Constant.OK);
		if (!"".equals(typeCode) || typeCode != null) {
			Object[] param = { typeCode, "1" };
			try {
				list = this.jpaDao.getResultData(Constant.ONE, number, jpql,
						param);
			} catch (MyException e) {
				result.setCode(Constant.FAILE_CODE);
				result.setMessage(e.getMessage());
				e.printStackTrace();
			}
		}
		if (list != null && list.size() > Constant.ZERO) {
			result.setTotalCount(list.size());
			for (Object o : list) {
				Object[] news = (Object[]) o;
				ContentBaseVo vo = new ContentBaseVo();
				vo.setId(Integer.valueOf(String.valueOf((news[Constant.ZERO]))));
				if (news[Constant.ONE] != null) {
					vo.setTitleImage(this.serverPath
							+ String.valueOf(news[Constant.ONE]));
				}
				lt.add(vo);
			}
			result.setList(lt);

		}
		return Response.ok(result).build();
	}

	/**
	 * get file with filename
	 * 
	 * @param application
	 *            ServletContext
	 * @param filename
	 *            String
	 * @param path
	 *            String
	 * @param postfix
	 *            String
	 * @return Response
	 */
	@SuppressWarnings("unused")
	private Response getFile(@Context ServletContext application,
			String filename, String path, String postfix) {
		String realPath = application.getRealPath(path);
		File file = new File(realPath, filename + postfix);
		if (!file.exists()) {
			throw new WebApplicationException(404);
		}
		String MimeFileType = new MimetypesFileTypeMap().getContentType(file);
		return Response
				.ok(file, MimeFileType)
				.header("Content-disposition",
						"attachment;filename=" + filename + postfix)
				.header("ragma", "No-cache")
				.header("Cache-Control", "no-cache").build();
	}

	protected boolean bigSize(InputStream input) {
		boolean result = false;
		try {
			int length = Constant.ZERO;
			int total = Constant.ZERO;
			byte[] buff = new byte[Constant.MD5_MAX_INDEX];
			while (Constant.NEGATIVE_ONE != (length = input.read(buff))) {
				total += length;
				if (total > Constant.MAX_IMAGE_SIZE) {
					result = true;
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				input.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}

}
